package com.dsteiner.xelavos.client.controller;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import com.dsteiner.widgets.client.IJsUtil;
import com.dsteiner.widgets.client.JsUtil;
import com.dsteiner.widgets.client.StringUtil;
import com.dsteiner.widgets.client.Widgets.IButton;
import com.dsteiner.widgets.client.Widgets.IHTML;
import com.dsteiner.widgets.client.Widgets.ILazyWidget;
import com.dsteiner.widgets.client.Widgets.IWidget;
import com.dsteiner.widgets.client.Widgets.TextInput;
import com.dsteiner.widgets.client.Widgets.WidgetListenerAdapter;
import com.dsteiner.widgets.client.event.EventManagerImpl;
import com.dsteiner.widgets.client.event.MessageEvent;
import com.dsteiner.widgets.client.model.PrefilledTextBoxModel;
import com.dsteiner.widgets.client.rpc.CrudResult;
import com.dsteiner.xelavos.client.constants.Constants;
import com.dsteiner.xelavos.client.domain.User;
import com.dsteiner.xelavos.client.model.AuthenticationModel;
import com.dsteiner.xelavos.client.rpc.DataService;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class LoginController {

	private IButton loginButton;
	private PrefilledTextBoxModel emailTextBoxModel;
	private PrefilledTextBoxModel passwordTextBoxModel;
	private AuthenticationModel authenticationModel;
	private IHTML forgotPasswordLink;
	private IHTML validateAccountLink;
	private CrudResult<User> loginResult;
	private IJsUtil jsUtil;

	public void registerAuthenticationModel(AuthenticationModel authenticationModel) {
		this.authenticationModel = authenticationModel;
		authenticationModel.addPropertyChangeListener("message", new PropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent evt) {
				updateForgotPasswordLinkVisibility();
				updateValidateAccountLinkVisibility();
			}
		});
	}

	public void registerEmailTextBoxModel(PrefilledTextBoxModel emailTextBoxModel) {
		this.emailTextBoxModel = emailTextBoxModel;
	}

	public void registerForgotPasswordLink(IHTML forgotPasswordLink) {
		this.forgotPasswordLink = forgotPasswordLink;
		forgotPasswordLink.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				String email = emailTextBoxModel.getText();
				DataService.Util.getInstance().sendPassword(email, new AsyncCallback<String>(){
					public void onFailure(Throwable arg0) {
						arg0.printStackTrace();
						authenticationModel.setMessage("un error occurio - intentelo otra vez");
					}
					public void onSuccess(String arg0) {
						authenticationModel.setMessage(arg0);
					}
				});
			}
		});
	}

	public void registerLoginButton(IButton loginButton) {
		this.loginButton = loginButton;
		loginButton.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event) {
				doLogin();
			}
		});
	}


	public void registerLoginWidget(ILazyWidget loginWidget) {
		loginWidget.addWidgetListener(new WidgetListenerAdapter(){
			@Override
			public void onAttach(IWidget widget) {
				updateForgotPasswordLinkVisibility();
				updateValidateAccountLinkVisibility();
			}
		});
	}

	public void registerPasswordTextBoxModel(PrefilledTextBoxModel passwordTextBoxModel) {
		this.passwordTextBoxModel = passwordTextBoxModel;
	}
	
	public void registerPasswordTextBox(TextInput passwordTextBox) {
		passwordTextBox.addKeyDownHandler(new KeyDownHandler(){
			public void onKeyDown(KeyDownEvent event) {
				int nativeKeyCode = event.getNativeKeyCode();
				if(KeyCodes.KEY_ENTER == nativeKeyCode){
					doLogin();
				}
			}
		});
	}

	private void updateForgotPasswordLinkVisibility() {
		String message = authenticationModel.getMessage();
		forgotPasswordLink.setVisible(Constants.MSG_PASSWORD_NOT_CORRECT.equals(message));
	}
	
	private void updateValidateAccountLinkVisibility() {
		String message = authenticationModel.getMessage();
		validateAccountLink.setVisible(Constants.MSG_VALIDATE_ACCOUNT.equals(message));
	}

	public void registerValidateAccountLink(IHTML validateAccountLink) {
		this.validateAccountLink = validateAccountLink;
		validateAccountLink.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				DataService.Util.getInstance().sendConfirmationMail(loginResult.getModelObject(), new AsyncCallback<Void>(){
					public void onFailure(Throwable arg0) {
						arg0.printStackTrace();
						authenticationModel.setMessage("un error occurio - intentelo otra vez");
					}
					public void onSuccess(Void arg0) {
						authenticationModel.setMessage(Constants.MSG_CONFIRMATION_EMAIL_SENT);
					}
				});
			}
		});
	}

	private void doLogin() {
		jsUtil.trackEvent(Constants.CAT_ACCOUNT, Constants.ACT_CLICKED_LOGIN_BUTTON);
		String email = emailTextBoxModel.getText();
		String password = passwordTextBoxModel.getText();
		StringBuffer sb = new StringBuffer();
		if(!emailTextBoxModel.isEdited() || email.length() < 4)
			sb.append("ingrese su email\n");
		if(!passwordTextBoxModel.isEdited())
			sb.append("ingrese su contraseña\n");
			
		if(sb.length() > 0){
			EventManagerImpl.getInstance().fireEvent(new MessageEvent(sb.toString()));
			return;
		}
		
		authenticationModel.setMessage("login...");
		DataService.Util.getInstance().getUser(email, password, new AsyncCallback<CrudResult<User>>(){
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
				authenticationModel.setMessage("login fallo - intente otra vez");
			}
			public void onSuccess(CrudResult<User> result) {
				LoginController.this.loginResult = result;
				if(!StringUtil.isEmpty(result.getError())){
					jsUtil.trackEvent(Constants.CAT_ACCOUNT, Constants.ACT_MSG_SHOWN, "Login Failure:"+result.getError());
					authenticationModel.setMessage(result.getError());
				}
				else{
					authenticationModel.setMessage(null);
					User user = result.getModelObject();
					authenticationModel.setUser(user);
					JsUtil.getInstance().trackGAVar(Constants.Util.getUserGAVar(user));
				}
			}
		});
	}

	public void registerJsUtil(IJsUtil jsUtil) {
		this.jsUtil = jsUtil;
	}
}
